#ifndef HAL_H
#define HAL_H

#include "stm32f0xx.h"
#define   PORTA  GPIOA
#define   PORTB  GPIOB

typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short  uint16;
typedef signed long int32;
typedef unsigned long uint32;
typedef uint8 u8;
typedef uint16 u16;
typedef uint32 u32;

typedef unsigned char       BOOL;

// Data
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;

// Unsigned numbers
typedef unsigned char       UINT8;
typedef unsigned char       INT8U;
typedef unsigned short      UINT16;
typedef unsigned short       INT16U;
typedef unsigned long       UINT32;
typedef unsigned long       INT32U;

// Signed numbers
typedef signed char         INT8;
typedef signed short        INT16;
typedef signed long         INT32;

//-----------------------------------------------------------------------------
// Common values
#ifndef FALSE
   #define FALSE 0
#endif

#ifndef TRUE
   #define TRUE 1
#endif

#ifndef NULL
   #define NULL 0
#endif

#ifndef HIGH
   #define HIGH 1
#endif

#ifndef LOW
   #define LOW 0
#endif

//#include "ioCC1110.h"
//#include "hal/ioCCxx10_bitdef.h"
//#include "hal/hal_clock.h"

#include "../hal/hal_led.h"
#include "../hal/hal_flash.h"
#include "../hal/hal_led.h"
#include "../hal/hal_rnd.h"
#include "../hal/hal_timer.h"
#include "../hal/hal_uart.h"
#include "../hal/hal_wait.h"
#include "../hal/hal_wdt.h"
#include "../hal/hal_aes.h"
#include "../hal/hal_sleep.h"
#include "../hal/hal_adc.h" 


#define HAL_ENTER_CRITICAL(i_state) i_state=1;__disable_irq();
#define HAL_EXIT_CRITICAL(i_state) if(i_state)__enable_irq();
#define HAL_ALL_INT_OFF() __disable_irq();
#define HAL_ALL_INT_ON() __enable_irq();
#ifdef OS_WDT
#define HAL_REBOOT()  NVIC_SystemReset();
#else
#define HAL_REBOOT() NVIC_SystemReset();
#endif

void hal_poll(void);
void hal_init(void);

extern INT8U LanguageSel;

#define IO_IN   0
#define IO_OUT  1

#define IO_IMODE_PORT_PIN(port, pin, imode) _IO_IMODE_PORT_PIN(port, pin, imode)

// where imode is one of:
#define IO_IMODE_PUD  0 // Pull-up/pull-down
#define IO_IMODE_TRI  1 // Tristate

#define IO_PULLUP          0
#define IO_PULLDOWN        1

#define IO_FUNC_PORT_PIN(port, pin, func) _IO_FUNC_PORT_PIN(port, pin, func)

#define IO_FUNC_GIO     0 // General purpose I/O
#define IO_FUNC_PERIPH  1 // Peripheral function

#define IO_ADC_EN           1 // ADC input enabled
#define IO_ADC_DIS          0 // ADC input disab

#define INT_ON   1
#define INT_OFF  0
#define INT_SET  1
#define INT_CLR  0


#define INUM_RFTXRX 0
#define INUM_ADC   1
#define INUM_URX0  2
#define INUM_URX1  3
#define INUM_ENC   4
#define INUM_ST    5
#define INUM_P2INT 6
#define INUM_UTX0  7
#define INUM_DMA   8
#define INUM_T1    9
#define INUM_T2    10
#define INUM_T3    11
#define INUM_T4    12
#define INUM_P0INT 13
#define INUM_UTX1  14
#define INUM_P1INT 15
#define INUM_RF    16
#define INUM_WDT   17

#define NBR_OF_INTERRUPTS 18


#define INT_PRIORITY(group, pri)                      \
   do {                                               \
      if (pri == 0) { IP0 &= ~group; IP1 &= ~group; } \
      if (pri == 1) { IP0 |=  group; IP1 &= ~group; } \
      if (pri == 2) { IP0 &= ~group; IP1 |=  group; } \
      if (pri == 3) { IP0 |=  group; IP1 |=  group; } \
   } while (0)


// Where group is one of
#define RFERR_RF_DMA    0x01 // Group IP0
#define ADC_P2INT_T1    0x02 // Group IP1
#define URX0_UTX0_T2    0x04 // Group IP2
#define URX1_UTX1_T3    0x08 // Group IP3
#define ENC_P1INT_T4    0x10 // Group IP4
#define ST_WDT_P0INT    0x20 // Group IP5


#define INT_GETFLAG(inum) (                       \
   (inum==INUM_RFTXRX)      ? RFTXRXIF          : \
   (inum==INUM_ADC)         ? ADCIF             : \
   (inum==INUM_URX0)        ? URX0IF            : \
   (inum==INUM_URX1)        ? URX1IF            : \
   (inum==INUM_ENC)         ? ENCIF_0           : \
   (inum==INUM_ST)          ? STIF              : \
   (inum==INUM_P2INT)       ? P2IF              : \
   (inum==INUM_UTX0)        ? UTX0IF            : \
   (inum==INUM_DMA)         ? DMAIF             : \
   (inum==INUM_T1)          ? T1IF              : \
   (inum==INUM_T2)          ? T2IF              : \
   (inum==INUM_T3)          ? T3IF              : \
   (inum==INUM_T4)          ? T4IF              : \
   (inum==INUM_P0INT)       ? P0IF              : \
   (inum==INUM_UTX1)        ? UTX1IF            : \
   (inum==INUM_P1INT)       ? P1IF              : \
   (inum==INUM_RF)          ? S1CON &= ~0x03    : \
   (inum==INUM_WDT)         ? WDTIF             : \
   0                                              \
)

#define INT_SETFLAG(inum, f)                     \
   do {                                          \
      if      (inum==INUM_RFTXRX){ RFTXRXIF = f; } \
      else if (inum==INUM_ADC)   { ADCIF  = f; } \
      else if (inum==INUM_URX0)  { URX0IF = f; } \
      else if (inum==INUM_URX1)  { URX1IF = f; } \
      else if (inum==INUM_ENC)   { ENCIF_1 = ENCIF_0 = f; } \
      else if (inum==INUM_ST)    { STIF  = f;  } \
      else if (inum==INUM_P2INT) { P2IF  = f;  } \
      else if (inum==INUM_UTX0)  { UTX0IF= f;  } \
      else if (inum==INUM_DMA)   { DMAIF = f;  } \
      else if (inum==INUM_T1)    { T1IF  = f;  } \
      else if (inum==INUM_T2)    { T2IF  = f;  } \
      else if (inum==INUM_T3)    { T3IF  = f;  } \
      else if (inum==INUM_T4)    { T4IF  = f;  } \
      else if (inum==INUM_P0INT) { P0IF  = f;  } \
      else if (inum==INUM_UTX1)  { UTX1IF= f;  } \
      else if (inum==INUM_P1INT) { P1IF  = f;  } \
      else if (inum==INUM_RF)    { (f) ? (S1CON |= 0x03) : (S1CON &= ~0x03); } \
      else if (inum==INUM_WDT)   { WDTIF = f;  } \
   } while (0)


#define DMA_CHANNEL_0  0x01
#define DMA_CHANNEL_1  0x02
#define DMA_CHANNEL_2  0x04
#define DMA_CHANNEL_3  0x08
#define DMA_CHANNEL_4  0x10

#define VLEN_USE_LEN            0x00 // Use LEN for transfer count
#define VLEN_FIXED              0x00 // Use LEN for transfer count
#define VLEN_1_P_VALOFFIRST     0x01 // Transfer the first byte + the number of bytes indicated by the first byte
#define VLEN_VALOFFIRST         0x02 // Transfer the number of bytes indicated by the first byte (starting with the first byte)
#define VLEN_1_P_VALOFFIRST_P_1 0x03 // Transfer the first byte + the number of bytes indicated by the first byte + 1 more byte
#define VLEN_1_P_VALOFFIRST_P_2 0x04 // Transfer the first byte + the number of bytes indicated by the first byte + 2 more bytes

#define WORDSIZE_BYTE           0x00 // Transfer a byte at a time
#define WORDSIZE_WORD           0x01 // Transfer a 16-bit word at a time

#define TMODE_SINGLE            0x00 // Transfer a single byte/word after each DMA trigger
#define TMODE_BLOCK             0x01 // Transfer block of data (length len) after each DMA trigger
#define TMODE_SINGLE_REPEATED   0x02 // Transfer single byte/word (after len transfers, rearm DMA)
#define TMODE_BLOCK_REPEATED    0x03 // Transfer block of data (after len transfers, rearm DMA)

#define DMATRIG_NONE           0   // No trigger, setting DMAREQ.DMAREQx bit starts transfer
#define DMATRIG_PREV           1   // DMA channel is triggered by completion of previous channel
#define DMATRIG_T1_CH0         2   // Timer 1, compare, channel 0
#define DMATRIG_T1_CH1         3   // Timer 1, compare, channel 1
#define DMATRIG_T1_CH2         4   // Timer 1, compare, channel 2
#define DMATRIG_T2_COMP        5   // Timer 2, compare
#define DMATRIG_T2_OVFL        6   // Timer 2, overflow
#define DMATRIG_T3_CH0         7   // Timer 3, compare, channel 0
#define DMATRIG_T3_CH1         8   // Timer 3, compare, channel 1
#define DMATRIG_T4_CH0         9   // Timer 4, compare, channel 0
#define DMATRIG_T4_CH1        10   // Timer 4, compare, channel 1
#define DMATRIG_ST            11   // Sleep Timer compare
#define DMATRIG_IOC_0         12   // Port 0 I/O pin input transition
#define DMATRIG_IOC_1         13   // Port 1 I/O pin input transition
#define DMATRIG_URX0          14   // USART0 RX complete
#define DMATRIG_UTX0          15   // USART0 TX complete
#define DMATRIG_URX1          16   // USART1 RX complete
#define DMATRIG_UTX1          17   // USART1 TX complete
#define DMATRIG_FLASH         18   // Flash data write complete
#define DMATRIG_RADIO         19   // RF packet byte received/transmit
#define DMATRIG_ADC_CHALL     20   // ADC end of a conversion in a sequence, sample ready
#define DMATRIG_ADC_CH0       21   // ADC end of conversion channel 0 in sequence, sample ready
#define DMATRIG_ADC_CH1       22   // ADC end of conversion channel 1 in sequence, sample ready
#define DMATRIG_ADC_CH2       23   // ADC end of conversion channel 2 in sequence, sample ready
#define DMATRIG_ADC_CH3       24   // ADC end of conversion channel 3 in sequence, sample ready
#define DMATRIG_ADC_CH4       25   // ADC end of conversion channel 4 in sequence, sample ready
#define DMATRIG_ADC_CH5       26   // ADC end of conversion channel 5 in sequence, sample ready
#define DMATRIG_ADC_CH6       27   // ADC end of conversion channel 6 in sequence, sample ready
#define DMATRIG_ADC_CH7       28   // ADC end of conversion channel 7 in sequence, sample ready
#define DMATRIG_ENC_DW        29   // AES encryption processor requests download input data
#define DMATRIG_ENC_UP        30   // AES encryption processor requests upload output data

#define SRCINC_0         0x00 // Increment source pointer by 0 bytes/words after each transfer
#define SRCINC_1         0x01 // Increment source pointer by 1 bytes/words after each transfer
#define SRCINC_2         0x02 // Increment source pointer by 2 bytes/words after each transfer
#define SRCINC_M1        0x03 // Decrement source pointer by 1 bytes/words after each transfer

#define DESTINC_0        0x00 // Increment destination pointer by 0 bytes/words after each transfer
#define DESTINC_1        0x01 // Increment destination pointer by 1 bytes/words after each transfer
#define DESTINC_2        0x02 // Increment destination pointer by 2 bytes/words after each transfer
#define DESTINC_M1       0x03 // Decrement destination pointer by 1 bytes/words after each transfer

#define IRQMASK_DISABLE  0x00 // Disable interrupt generation
#define IRQMASK_ENABLE   0x01 // Enable interrupt generation upon DMA channel done

#define M8_USE_8_BITS    0x00 // Use all 8 bits for transfer count
#define M8_USE_7_BITS    0x01 // Use 7 LSB for transfer count

#define PRI_LOW          0x00 // Low, CPU has priority
#define PRI_GUARANTEED   0x01 // Guaranteed, DMA at least every second try
#define PRI_HIGH         0x02 // High, DMA has priority
#define PRI_ABSOLUTE     0x03 // Highest, DMA has priority. Reserved for DMA port access.


// Options for UART_SETUP macro
#define FLOW_CONTROL_ENABLE         0x40
#define FLOW_CONTROL_DISABLE        0x00
#define EVEN_PARITY                 0x20
#define ODD_PARITY                  0x00
#define NINE_BIT_TRANSFER           0x10
#define EIGHT_BIT_TRANSFER          0x00
#define PARITY_ENABLE               0x08
#define PARITY_DISABLE              0x00
#define TWO_STOP_BITS               0x04
#define ONE_STOP_BITS               0x00
#define HIGH_STOP                   0x02
#define LOW_STOP                    0x00
#define HIGH_START                  0x01
#define TRANSFER_MSB_FIRST          0x80
#define TRANSFER_MSB_LAST           0x00


// Example usage:
//   if(UART0_PARERR())
//     ...
#define UART_PARERR(num)      ((U##num##CSR & 0x08) == 0x08)
#define UART0_PARERR()        UART_PARERR(0)
#define UART1_PARERR()        UART_PARERR(1)

// Example usage:
//   if(UART1_FRAMEERR())
//     ...
#define UART_FRAMEERR(num)    ((U ##num## CSR & 0x10) == 0x10)
#define UART0_FRAMEERR()      UART_FRAMEERR(0)
#define UART1_FRAMEERR()      UART_FRAMEERR(1)



#define UART_SEND(num, x)   U##num##DBUF = x
#define UART0_SEND(x)       UART_SEND(0, x)
#define UART1_SEND(x)       UART_SEND(1, x)

#define UART_RECEIVE(num, x)  x = U##num##DBUF
#define UART0_RECEIVE(x)      UART_RECEIVE(0, x)
#define UART1_RECEIVE(x)      UART_RECEIVE(1, x)

#define SPI_SLAVE              0x01
#define SPI_MASTER             0x00
#define SPI_CLOCK_POL_LO       0x00
#define SPI_CLOCK_POL_HI       0x80
#define SPI_CLOCK_PHA_0        0x00
#define SPI_CLOCK_PHA_1        0x40
#define SPI_TRANSFER_MSB_FIRST 0x20
#define SPI_TRANSFER_MSB_LAST  0x00

#define READ_WHEN_NEED  0x00
#define CONTINOUS_READ  0x10
//#define WRITE           0x02
#define ERASE           0x01
#define FLASH_BUSY      0x80

void halFlashWritePage(BYTE *pSrcAddr, BYTE *pBuffer, BYTE page);

void halFlashErasePage(BYTE* buffer, BYTE page);

// Where _mode_ is one of
#define POWER_MODE_0  0x00  // Clock oscillators on, voltage regulator on
#define POWER_MODE_1  0x01  // 32.768 KHz oscillator on, voltage regulator on
#define POWER_MODE_2  0x02  // 32.768 KHz oscillator on, voltage regulator off
#define POWER_MODE_3  0x03  // All clock oscillators off, voltage regulator off

#define CRYSTAL 0x00
#define RC      0x01

// where frequency is one of
#define MHZ_26          0x00
#define MHZ_13          0x01
#define MHZ_6_5         0x02
#define MHZ_3_25        0x03
#define MHZ_1_62        0x04
#define MHZ_0_81        0x05
#define MHZ_0_40        0x06
#define MHZ_0_20        0x07

WORD halSetTimer1Period(DWORD period);

#define POS_EDGE 0x01  // Capture when a positive edge on the channel input is detected
#define NEG_EDGE 0x02  // Capture when a negative edge on the channel input is detected
#define ANY_EDGE 0x03  // Capture when either a positive or a negative edge on the
                       // channel input is detected.
BOOL halSetTimer2Period(UINT32 period, UINT8* cnt, UINT8* presc);


#define TIMER2_USE_REG  FALSE
#define TIMER2_FREE     TRUE


BYTE halSetTimer34Period(BYTE timer, DWORD period);

#define SLEEP_TIMER_INIT()                                    \
   do{                                                        \
      WOREVT1 = 0x87;                                         \
      WOREVT0 = 0x6B;                                         \
      WORCTL = 0x74;                                          \
      WORIRQ = 0x00;                                          \
   } while(0)

// Where _timeout_ is one of
#define SEC_1          0x00     // after 1 second
#define M_SEC_250      0x01     // after 250 ms
#define M_SEC_15       0x02     // after 15 ms
#define M_SEC_2        0x03     // after 2 ms

#define ADC_REF_1_25_V      0x00     // Internal 1.25V reference
#define ADC_REF_P0_7        0x40     // External reference on AIN7 pin
#define ADC_REF_AVDD        0x80     // AVDD_SOC pin
#define ADC_REF_P0_6_P0_7   0xC0     // External reference on AIN6-AIN7 differential input

// Resolution (decimation rate):
#define ADC_8_BIT           0x00     //  64 decimation rate
#define ADC_10_BIT          0x10     // 128 decimation rate
#define ADC_12_BIT          0x20     // 256 decimation rate
#define ADC_14_BIT          0x30     // 512 decimation rate
// Input channel:
#define ADC_AIN0            0x00     // single ended P0_0
#define ADC_AIN1            0x01     // single ended P0_1
#define ADC_AIN2            0x02     // single ended P0_2
#define ADC_AIN3            0x03     // single ended P0_3
#define ADC_AIN4            0x04     // single ended P0_4
#define ADC_AIN5            0x05     // single ended P0_5
#define ADC_AIN6            0x06     // single ended P0_6
#define ADC_AIN7            0x07     // single ended P0_7
#define ADC_GND             0x0C     // Ground
#define ADC_TEMP_SENS       0x0E     // on-chip temperature sensor
#define ADC_VDD_3           0x0F     // (vdd/3)

INT16 halAdcSampleSingle(BYTE reference, BYTE resolution, UINT8 input);

INT16 halGetAdcValue(void);

//BYTE halRfSendPacket(BYTE* pData, BYTE length);

//BYTE halRfReceivePacket(BYTE* pData, BYTE*pRssi, BYTE* pLqi, BYTE timeOut);


BOOL halRfConfig(UINT32 frequency);

void halRfSetRadioFrequency(UINT32 frequency);



#define STOP_RADIO()        SIDLE();
// RF interrupt flags
#define IRQ_TXUNF           0x80
#define IRQ_RXOVF           0x40
#define IRQ_TIMEOUT         0x20
#define IRQ_DONE            0x10
#define IRQ_CS              0x08
#define IRQ_PQT             0x04
#define IRQ_CCA             0x02
#define IRQ_SFD             0x01

// RF status flags
#define CRC_OK_FLAG         0x80
#define CS_FLAG             0x40
#define PQT_REACHED_FLAG    0x20
#define CCA_FLAG            0x10
#define SFD_FLAG            0x08

// Radio status flags
#define CRC_OK_FLAG         0x80
#define CS_FLAG             0x40
#define PQT_REACHED_FLAG    0x20
#define CCA_FLAG            0x10
#define SFD_FLAG            0x08



// Various radio settings
#define APPEND_STATUS         0x04
#define WHITE_DATA            0x40
#define CRC_EN                0x04
#define VARIABLE_PKT_LEN      0x01
#define STAY_INR_RX_AFTER_RX  0x0C
#define RX_AFTER_TX           0x03
#define CALIBRATE_WHEN_COMING_FROM_IDLE   0x10
#define CALIBRATE_EVERY_4TH   0x30
#define PA_POWER_7            0x07
#define PA_POWER_0            0x00

// Conditions _c_ for the RPT and SKIP instructions of the CSP
#define CCA_TRUE            0x00;
#define RECEIVING           0x01;
#define MCU_BIT_IS_1        0x02;
#define COMMAND_BUF_EMPT    0x03;
#define REGX_IS_0           0x04;
#define REGY_IS_0           0x05;
#define REGZ_IS_0           0x06;
#define NO_OP               0x07;

void halAesLoadKeyOrInitVector(BYTE* pData, BOOL key);

void halAesEncrDecr(BYTE* pDataIn, UINT16 length, BYTE* pDataOut, BYTE* pInitVector, BOOL decr);


#define AES_BUSY    0x08
#define ENCRYPT     0x00
#define DECRYPT     0x01

// _mode_ is one of
#define CBC         0x00
#define CFB         0x10
#define OFB         0x20
#define CTR         0x30
#define ECB         0x40
#define CBC_MAC     0x50

// Where _mode_ is one of
#define AES_ENCRYPT     0x00
#define AES_DECRYPT     0x02
#define AES_LOAD_KEY    0x04
#define AES_LOAD_IV     0x06

// Macro for getting a random byte
#define GET_RANDOM_BYTE(a)      \
   do{                           \
      CLOCK_RANDOM_GENERATOR();  \
      a = RNDL;                  \
   }while(0)


#define GET_RANDOM_WORD(a)      \
   do{                           \
      CLOCK_RANDOM_GENERATOR();  \
      a = (((WORD)RNDH << 8) | RNDL);                  \
   }while(0)

void halInitRandomGenerator(void);
void halWait(unsigned long wait);

//int putchar(int i);

#endif //HAL_H
